package com.mobile.exception;

import java.util.ArrayList;
import java.util.List;

import com.mobile.tools.Message;

/**
 * 应用级异常（业务人员误操作产生的异常，如用户不存在、密码错误等等）的基类，是一个受控异常基类。
 * <p/>
 * 对于Checked Excpetion:
 * <p/>
 * 1)定义方法时必须声明所有可能会抛出的checked exception; <br>
 * 2)在调用这个方法时，必须捕获(try/catch)它的checked exception，或者把它的exception传递下去; <br>
 * 3)继承于受控类java.lang.Exception  <br>
 * <p/>
 * * 示例如下：<br>
 * <pre>
 * 1)抛出错误(Service)
 * public void loginCheck(String username,String password) throws BaseCheckedException {
 *      ...
 *      throw new BaseCheckedException("e_login_user_isnotexist",new Object[]{username,password});
 *      ...
 *      throw new BaseCheckedException("e_login_password_error",new Object[]{username,password});
 *      ...
 * }
 * <p/>
 * 2)捕捉错误(Action)
 * public login() {
 *      try {
 *           xxxService.loginCheck();
 *      } catch(BaseCheckedException ex) {
 *          //如果只抛出一种错误，可不加if 条件判断
 *           if (ex.getExceptionKey().equals("e_login_user_isnotexist")) {
 *               ...
 *               this.hintErrorMessage(ex.getMessage());
 *           }
 * <p/>
 *           if (ex.getExceptionKey().equals("e_login_password_error")) {
 *               ...
 *               this.hintErrorMessage(ex.getMessage());
 *           }
 *      }
 * }
 * </pre>
 *
 */
public class BaseCheckedException extends Exception {

    /**
     * 错误Key，用于唯一标识错误类型。
     * exceptionKey必须在common/applicationMessage.properties中定义。
     */
    private String exceptionKey = null;

    /**
     * 传递给变量的错误值
     */
    private Object[] exceptionValues = null;

    /**
     * 根据Key从资源文件转成明文的错误信息
     */
    private String message = null;

    public BaseCheckedException() {
        super();
    }
    public BaseCheckedException(String message, Throwable ex) {
        super(message, ex);
    }

    public BaseCheckedException(String key) {
    	super(Message.getMessage(key));
        this.exceptionKey = key;
        this.exceptionValues = null;
        //转成明文错误信息
        message = Message.getMessage(key);        
    }

    public BaseCheckedException(String key, String message) {
        super(message);
        this.exceptionKey = key;
        this.message = message;
    }

    public BaseCheckedException(String key, Object[] args) {
        super(Message.getMessage(key, args));
        this.exceptionKey = key;
        this.exceptionValues = args;
        //转成明文错误信息
        this.message = Message.getMessage(key, args);
    }

    public BaseCheckedException(Throwable rootCause, String key, Object[] args) {
        super(rootCause);
        this.exceptionKey = key;
        this.exceptionValues = args;
        //转成明文错误信息
        this.message = Message.getMessage(key, args);
    }
	public BaseCheckedException(Throwable cause) {
		super(cause);
	}

    public Object[] getExceptionValues() {
        return exceptionValues;
    }

    /**
     * 获取异常Key
     *
     * @return 异常Key
     */
    public String getExceptionKey() {
        return exceptionKey;
    }

    /**
     * 取得转成明文的错误信息
     *
     * @return String 返回转成明文的错误信息
     */
    public String getMessage() {
        return message == null || message.trim().equals("") ? super.getMessage() : message;
    }

    public String getMessagesString() {
        String[] msgs = this.getMessages();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < msgs.length; i++) {
            sb.append(msgs[i] + "\n");
        }
        return sb.toString();
    }

    public String[] getMessages() {
        Throwable[] throwables = this.getThrowables();
        String[] msgs = new String[throwables.length];
        for (int i = 0; i < throwables.length; i++) {
            msgs[i] = throwables[i].getMessage();
        }
        return msgs;
    }

    public Throwable[] getThrowables() {
        List list = new ArrayList();
        Throwable throwable = this;
        while (throwable != null) {
            list.add(throwable);
            throwable = throwable.getCause();
        }
        return (Throwable[]) list.toArray(new Throwable[list.size()]);
    }
}